home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 April: Mac OS SDK / Dev.CD Apr 97 SDK1.toast / Development Kits (Disc 1) / Apple Shared Library Manager / ASLM Examples / Inspector / Sources / Application.cp next >
Encoding:
Text File  |  1996-11-19  |  13.6 KB  |  550 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Application.cp
  3.  
  4.     Contains:    TApplication implementation.
  5.  
  6.     Copyright:    © 1991-1994 by Apple Computer, Inc., all rights reserved.
  7.  
  8. */
  9.  
  10. #ifndef __TYPES__
  11. #include <Types.h>
  12. #endif
  13.  
  14. #ifndef __QUICKDRAW__
  15. #include <QuickDraw.h>
  16. #endif
  17. #ifndef __FONTS__
  18. #include <Fonts.h>
  19. #endif
  20. #ifndef __EVENTS__
  21. #include <Events.h>
  22. #endif
  23. #ifndef __WINDOWS__
  24. #include <Windows.h>
  25. #endif
  26. #ifndef __MENUS__
  27. #include <Menus.h>
  28. #endif
  29. #ifndef __DIALOGS__
  30. #include <Dialogs.h>
  31. #endif
  32. #ifndef __TOOLUTILS__
  33. #include <ToolUtils.h>
  34. #endif
  35. #ifndef __MEMORY__
  36. #include <Memory.h>
  37. #endif
  38.  
  39. #ifndef __SEGLOAD__
  40. #include <SegLoad.h>
  41. #endif
  42. #ifndef __OSUTILS__
  43. #include <OSUtils.h>
  44. #endif
  45. #ifndef __TRAPS__
  46. #include <Traps.h>
  47. #endif
  48.  
  49. #ifndef __APPLICATION__
  50. #include "Application.h"
  51. #endif
  52. #ifndef __SIMPLECOMMON__
  53. #include "SimpleCommon.h"
  54. #endif
  55. #ifndef __APPLICATIONCOMMON__
  56. #include "ApplicationCommon.h"
  57. #endif
  58. #ifndef __DOCUMENT__
  59. #include "Document.h"
  60. #endif
  61.  
  62. #include "TrapAvailable.cp"
  63.  
  64. // OSEvent is the event number of the suspend/resume and mouse-moved events sent
  65. // by MultiFinder. Once we determine that an event is an osEvent, we look at the
  66. // high byte of the message sent to determine which kind it is. To differentiate
  67. // suspend and resume events we check the resumeMask bit.
  68. const short kOsEvent = app4Evt;                // event used by MultiFinder
  69. const short kSuspendResumeMessage = 0x01;    // high byte of suspend/resume event message
  70. const short kClipConvertMask = 0x02;        // bit of message field clip conversion
  71. const short kResumeMask = 0x01;                // bit of message field for resume vs. suspend
  72. const short kMouseMovedMessage = 0xFA;        // high byte of mouse-moved event message
  73.  
  74. /*******************************************************************************
  75. ** PUBLIC Constructor/Destructor
  76. ********************************************************************************/
  77.  
  78. TApplication::TApplication()
  79. {
  80.     fCurDoc = NULL;
  81.     fDone = NULL;
  82.     fInBackground = false;
  83.     fMouseRgn = NULL;
  84.     fWhichWindow = NULL;
  85.     fqd = NULL;
  86. }
  87.  
  88. TApplication::TApplication(QDGlobals* qdPtr, BooleanParm initToolbox)
  89. {
  90.     InitApplication(qdPtr, initToolbox);
  91. }
  92.  
  93. TApplication::~TApplication(void)
  94. {
  95.     //Trace("Disposing TApplication\n");
  96.     delete fDocList;
  97. }
  98.  
  99. /*******************************************************************************
  100. ** PRIVATE InitApplication
  101. ********************************************************************************/
  102.  
  103. void TApplication::InitApplication(QDGlobals* qdPtr, Boolean initToolbox)
  104. {
  105.     SysEnvRec envRec;
  106.     long stkNeeded, heapSize;
  107.     fqd = qdPtr;
  108.  
  109.     // initialize Mac Toolbox components
  110.     if (initToolbox) {
  111.         InitGraf(&fqd->thePort);
  112.         InitFonts();
  113.         InitWindows();
  114.         InitMenus();
  115.         TEInit();
  116.         InitDialogs(NULL);
  117.         InitCursor();
  118.     }
  119.  
  120.     // ignore the error returned from SysEnvirons; even if an error occurred,
  121.     // the SysEnvirons glue will fill in the SysEnvRec
  122.     (void) SysEnvirons(curSysEnvVers, &envRec);
  123.  
  124.     // Are we running on a 128K ROM machine or better???
  125.     if (envRec.machineType < 0) {
  126.         TApplication::BigBadError(kApplicationErrStrings,eWrongMachine); // if not, alert & quit
  127.     }
  128.  
  129.     // if we need more stack space, get it now
  130.     stkNeeded = StackNeeded();
  131.     if (stkNeeded > StackSpace())
  132.       {
  133.         // new address is heap size + current stack - needed stack
  134.         SetApplLimit((Ptr) ((long) GetApplLimit() - stkNeeded + StackSpace()));
  135.       }
  136.  
  137.     // Check for minimum heap size
  138.     heapSize = (long) GetApplLimit() - (long) ApplicationZone();
  139.     if (heapSize < HeapNeeded()) {
  140.         TApplication::BigBadError(kApplicationErrStrings,eSmallSize);
  141.     }
  142.  
  143.     // expand the heap so new code segments load at the top
  144.     MaxApplZone();
  145.  
  146.     // allocate an empty document list
  147.     fDocList = new TDocumentList;
  148.  
  149.     // check to see if WaitNextEvent is implemented
  150.     fHaveWaitNextEvent = TrapAvailable(_WaitNextEvent);
  151.  
  152.     // initialize our class variables
  153.     fCurDoc = NULL;
  154.     fDone = false;
  155.     fInBackground = false;
  156.     fMouseRgn = NULL;
  157.     fWhichWindow = NULL;
  158. }
  159.  
  160. /**********************************************************************
  161. ** PUBLIC EventLoop
  162. ***********************************************************************/
  163.  
  164. void TApplication::EventLoop(void)
  165. {
  166.     int gotEvent;
  167.     EventRecord tEvt;
  168.  
  169.     SetUp();                    // call setup routine
  170.     DoIdle();                    // do idle once
  171.  
  172.     while (fDone == false)
  173.       {
  174.         // always set up fWhichWindow before doing anything
  175.         fWhichWindow = FrontWindow();
  176.         // see if window belongs to a document
  177.         fCurDoc = fDocList->FindDoc(fWhichWindow);
  178.         // make sure we always draw into correct window
  179.         SetPort(fWhichWindow);
  180.  
  181.         DoIdle();            // call idle time handler
  182.         
  183.         if (fHaveWaitNextEvent)
  184.           {
  185.               //DebugStr((ConstStr255Param)"\pJust before WaitNextEvent");
  186.             gotEvent = WaitNextEvent(everyEvent, &tEvt, SleepVal(), fMouseRgn);
  187.           }
  188.         else
  189.           {
  190.             SystemTask();
  191.             gotEvent = GetNextEvent(everyEvent, &tEvt);
  192.           }
  193.         fTheEvent = tEvt;
  194.  
  195.         // make sure we got a real event
  196.         if ( gotEvent )
  197.           {
  198.             AdjustCursor();
  199.             switch (fTheEvent.what)
  200.               {
  201.                 case mouseDown :
  202.                     DoMouseDown();
  203.                     break;
  204.                 case mouseUp :
  205.                     DoMouseUp();
  206.                     break;
  207.                 case keyDown :
  208.                 case autoKey :
  209.                     DoKeyDown();
  210.                     break;
  211.                 case updateEvt :
  212.                     DoUpdateEvt();                
  213.                     break;
  214.                 case diskEvt :
  215.                     DoDiskEvt();
  216.                     break;
  217.                 case activateEvt :
  218.                     DoActivateEvt();
  219.                     break;
  220.                 case kOsEvent :
  221.                     DoOSEvent();
  222.                     break;
  223.                 default :
  224.                     break;
  225.               } // end switch (fTheEvent.what)
  226.           }
  227.         AdjustCursor();
  228.       }
  229.     // call cleanup handler
  230.     CleanUp();
  231. }
  232.  
  233. /**********************************************************************
  234. ** PUBLIC StackNeeded/HeapNeeded
  235. ***********************************************************************/
  236.  
  237. long TApplication::StackNeeded()
  238. {
  239.     return 0;
  240. }
  241.  
  242. long TApplication::HeapNeeded()
  243. {
  244.     return 0;
  245. }
  246.  
  247. /**********************************************************************
  248. ** PUBLIC SetUp/Cleanup
  249. ***********************************************************************/
  250.  
  251. void TApplication::SetUp()
  252. {
  253.     // Run before event loop starts
  254. }
  255.  
  256. void TApplication::CleanUp()
  257. {
  258.     // run at end of loop
  259. }
  260.  
  261. /**********************************************************************
  262. ** PUBLIC ExitLoop
  263. ***********************************************************************/
  264.  
  265. void TApplication::ExitLoop(void)
  266. {
  267.     fDone = true;
  268. }
  269.  
  270. /**********************************************************************
  271. ** PUBLIC DoIdle
  272. ***********************************************************************/
  273.  
  274. void TApplication::DoIdle()
  275. {
  276.     // idle time handler (blink caret, background tasks)
  277. }
  278.  
  279. /**********************************************************************
  280. ** PUBLIC AdjustMenus
  281. ***********************************************************************/
  282.  
  283. void TApplication::AdjustMenus()
  284. {
  285.     // menu updater routine
  286. }
  287.  
  288. /**********************************************************************
  289. ** PUBLIC DoKeyDown
  290. ***********************************************************************/
  291.  
  292. void TApplication::DoKeyDown(void)
  293. {
  294.     char key;
  295.     long mResult;
  296.  
  297.     key = (char) (fTheEvent.message & charCodeMask);
  298.     if ((fTheEvent.modifiers & cmdKey) && (fTheEvent.what == keyDown))
  299.       {
  300.         // only do command keys if we are not autokeying
  301.         AdjustMenus();                    // make sure menus are up to date
  302.         mResult = MenuKey(key);
  303.         if (mResult != 0)                // if it wasn't a menu key, pass it through
  304.           {
  305.             DoMenuCommand(HiWrd(mResult), LoWrd(mResult));
  306.             return;
  307.           }
  308.       }
  309.     if (fCurDoc != NULL)
  310.       {
  311.         EventRecord tEvt;
  312.  
  313.         // we copy event record so that we don't pass reference to object field 
  314.         tEvt = fTheEvent;
  315.         fCurDoc->DoKeyDown(&tEvt);
  316.       }
  317. }
  318.  
  319. /**********************************************************************
  320. ** PUBLIC DoActivateEvt/DoUpdateEvt
  321. ***********************************************************************/
  322.  
  323. void TApplication::DoActivateEvt(void)
  324. {
  325.     // event record contains window ptr
  326.     fWhichWindow = (WindowPtr) fTheEvent.message;
  327.     // see if window belongs to a document
  328.     fCurDoc = fDocList->FindDoc(fWhichWindow);
  329.     SetPort(fWhichWindow);
  330.  
  331.     if (fCurDoc != NULL)
  332.       fCurDoc->DoActivate((fTheEvent.modifiers & activeFlag) != 0);
  333. }
  334.  
  335. void TApplication::DoUpdateEvt(void)
  336. {
  337.     // event record contains window ptr
  338.     fWhichWindow = (WindowPtr) fTheEvent.message;
  339.     // see if window belongs to a document
  340.     fCurDoc = fDocList->FindDoc(fWhichWindow);
  341.     SetPort(fWhichWindow);
  342.  
  343.     if (fCurDoc != NULL)
  344.       fCurDoc->DoUpdate();
  345. }
  346.  
  347. /**********************************************************************
  348. ** PUBLIC DoOSEvent
  349. ***********************************************************************/
  350.  
  351. void TApplication::DoOSEvent(void)
  352. {
  353.     Boolean doConvert;
  354.     unsigned char evType;
  355.  
  356.     // is it a multifinder event?
  357.     evType = (unsigned char) (fTheEvent.message >> 24) & 0x00ff;
  358.     switch (evType) {     // high byte of message is type of event
  359.         case kMouseMovedMessage :
  360.             DoIdle();                    // mouse-moved is also an idle event
  361.             break;
  362.         case kSuspendResumeMessage :
  363.             doConvert = (fTheEvent.message & kClipConvertMask) != 0;
  364.             fInBackground = (fTheEvent.message & kResumeMask) == 0;
  365.             if (fInBackground)
  366.               DoSuspend(doConvert);
  367.             else DoResume(doConvert);
  368.             break;
  369.     }
  370. }
  371.  
  372. /**********************************************************************
  373. ** PUBLIC DoMouseDown
  374. ***********************************************************************/
  375.  
  376. void TApplication::DoMouseDown(void)
  377. {
  378.     long mResult;
  379.     short partCode;
  380.     WindowPtr tWind;
  381.     EventRecord tEvt;
  382.  
  383.     // gotta watch those object field dereferences
  384.     partCode = FindWindow(fTheEvent.where, &tWind);
  385.     fWhichWindow = tWind;
  386.     tEvt = fTheEvent;
  387.     switch (partCode)
  388.       {
  389.         case inSysWindow :
  390.             DoMouseInSysWindow();
  391.             break;
  392.         case inMenuBar :
  393.             AdjustMenus();
  394.             mResult = MenuSelect(tEvt.where);
  395.             if (mResult != 0)
  396.               DoMenuCommand(HiWrd(mResult),LoWrd(mResult));
  397.             break;
  398.         case inGoAway :
  399.             DoGoAway();                    
  400.             break;
  401.         case inDrag :
  402.             DoDrag();
  403.             break;
  404.         case inGrow :
  405.             if (fCurDoc != NULL)
  406.               fCurDoc->DoGrow(&tEvt);                    
  407.             break;
  408.         case inZoomIn :
  409.         case inZoomOut :
  410.             if ((TrackBox(fWhichWindow, tEvt.where, partCode)) &&
  411.                 (fCurDoc != NULL))
  412.               fCurDoc->DoZoom(partCode);
  413.             break;
  414.         case inContent :
  415.             // If window is not in front, make it so
  416.             if ( fWhichWindow != FrontWindow() )
  417.               SelectWindow(fWhichWindow);
  418.             else if (fCurDoc != NULL)
  419.               fCurDoc->DoContent(&tEvt);                    
  420.             break;
  421.       }
  422. }
  423.  
  424. /**********************************************************************
  425. ** PUBLIC DoMouseInSysWindow
  426. ***********************************************************************/
  427.  
  428. void TApplication::DoMouseInSysWindow()
  429. {
  430.     SystemClick(&fTheEvent, fWhichWindow);
  431. }
  432.  
  433. /**********************************************************************
  434. ** PUBLIC DoDrag
  435. ***********************************************************************/
  436.  
  437. void TApplication::DoDrag(void)
  438. {
  439.     DragWindow(fWhichWindow, fTheEvent.where, &fqd->screenBits.bounds);
  440. }
  441.  
  442. /**********************************************************************
  443. ** PUBLIC DoGoAway
  444. ***********************************************************************/
  445.  
  446. void TApplication::DoGoAway(void)
  447. {
  448.     if (TrackGoAway(fWhichWindow, fTheEvent.where)) {
  449.         if (fCurDoc != NULL)
  450.             HideWindow(fCurDoc->GetDocWindow());
  451.         else
  452.             CloseDeskAcc(((WindowPeek) fWhichWindow)->windowKind);
  453.  
  454.         // make sure our current document/window references are valid
  455.         fWhichWindow = FrontWindow();
  456.         if (fWhichWindow != NULL) {
  457.             fCurDoc = fDocList->FindDoc(fWhichWindow);
  458.             SetPort(fWhichWindow);
  459.         }
  460.         else fCurDoc = NULL;
  461.     }
  462. }
  463.  
  464. /**********************************************************************
  465. ** PUBLIC AdjustCursor
  466. ***********************************************************************/
  467.  
  468. void TApplication::AdjustCursor()
  469. {
  470.     // cursor adjust routine, should setup mouseRgn
  471. }
  472.  
  473. /**********************************************************************
  474. ** PUBLIC DoMenuCommand
  475. ***********************************************************************/
  476.  
  477. void TApplication::DoMenuCommand(short, short)
  478. {
  479. }
  480.  
  481. /**********************************************************************
  482. ** PUBLIC DoSuspend/DoResume
  483. ***********************************************************************/
  484.  
  485. void TApplication::DoSuspend(Boolean doClipConvert)
  486. {
  487.     doClipConvert = false;        // this is here because I HATE compiler warnings!!
  488.     if (fCurDoc != NULL)
  489.       fCurDoc->DoActivate(!fInBackground);
  490. }
  491.  
  492. void TApplication::DoResume(Boolean doClipConvert)
  493. {
  494.     doClipConvert = false;        // this is here because I HATE compiler warnings!!
  495.     if (fCurDoc != NULL)
  496.       fCurDoc->DoActivate(!fInBackground);
  497. }
  498.  
  499. /**********************************************************************
  500. ** PUBLIC DoMenuCommand
  501. ***********************************************************************/
  502.  
  503. void TApplication::DoMouseUp()
  504. {
  505. }
  506.  
  507. /**********************************************************************
  508. ** PUBLIC DoDiskEvt
  509. ***********************************************************************/
  510.  
  511. void TApplication::DoDiskEvt()
  512. {
  513. }
  514.  
  515. /**********************************************************************
  516. ** PUBLIC SleepVal
  517. ***********************************************************************/
  518.  
  519. unsigned long TApplication::SleepVal()
  520. {
  521.     return 20;        // how long to sleep in WaitNextEvent
  522. }
  523.  
  524. /**********************************************************************
  525. **  TApplication static methods
  526. ***********************************************************************/
  527.  
  528. void TApplication::AlertUser(short errResID, short errCode)
  529. {
  530.     Str255 message;
  531.     long savedRefNum;
  532.     GetLocalLibraryFile()->Preflight(savedRefNum);
  533.  
  534.     GetIndString(message, errResID, errCode);
  535.     #if qDebug
  536.     if (message[0] == 0)
  537.         DebugStr((ConstStr255Param)"\pTApplication::AlertUser could not get error string.");
  538.     #endif
  539.     ParamText(message, (ConstStr255Param)"\p", (ConstStr255Param)"\p", (ConstStr255Param)"\p");
  540.     (void) Alert(rUserAlert, NULL);
  541.  
  542.     GetLocalLibraryFile()->Postflight(savedRefNum);
  543. }
  544.  
  545. void TApplication::BigBadError(short errResID, short errCode)
  546. {
  547.     TApplication::AlertUser(errResID,errCode);
  548.     ExitToShell();
  549. }
  550.